import { GameConfig } from "../configs/GameConfig";
import { ISubLevelElement } from "../configs/SubLevel";
import { AdsUtil } from "../etc/AdsUtil";
import { Attribute } from "../etc/Attribute";
import { updater } from "../etc/Updater";
import { CheckPoint } from "../gameEtc/CheckPoint";
import { AutoAdsWindow } from "../ui/AutoAdsWindow";
import { ResurgenceWindow } from "../ui/RecurgenceWindow";
import { PlayerModuleC, PlayerModuleS } from "./PlayerModule";

class CheckPointMapping {
    private static mapping: Map<number, ISubLevelElement[]>

    static getCheckPointArrayByKind(kind: number) {
        this.mappingChecker()
        return this.mapping.get(kind)
    }

    private static mappingChecker() {
        if (this.mapping) return
        this.mapping = new Map()
        for (const cfg of GameConfig.Checkpoint.getAllElement()) {
            if (!this.mapping.has(cfg.Kind)) this.mapping.set(cfg.Kind, [])
            this.mapping.get(cfg.Kind).push(cfg)
        }
    }
}

export class LevelModuleData extends Subdata {
    @Decorator.persistence()
    checkPointID: number

    protected initDefaultData(): void {
        this.checkPointID = 1
    }
}

export class LevelModuleC extends ModuleC<LevelModuleS, LevelModuleData>{
    onPlayerDeadEvent: Action = new Action()
    onLevelChanged:Action1<number> = new Action()
    isDead:boolean = false

    private checkpoint: CheckPoint
    private checkpointEffect: GameObject

    protected onStart() {
        this.checkpointEffect = GameObject.findGameObjectById("18548D61")
        // 初始化检查点
        this.checkpoint = new CheckPoint(GameConfig.Checkpoint.getElement(this.data.checkPointID), this.onEnterNextCheckpoint, this)
        // 设置玩家位置初始
        this.resetPlayerPositionToCurrentCheckpointStartPosition()
        // 设置检查点特效
        this.resetCheckpointEffect()

        InputUtil.onKeyDown(Keys.F5, ()=>{
            UIService.show(AutoAdsWindow)
        })
    }

    protected onUpdate(): void { }

    // 当播放弹窗广告成功后(给用户发奖励)
    playLevelAutoAdsSuccess(){
        this.server.net_player_play_ads_success()
    }

    // 五分钟插播一次
    @updater.updateByFrameInterval(30 * 60 * 3)
    private autoPlayAds(){
        UIService.show(AutoAdsWindow)
    }

    // 死亡检测
    @updater.updateByFrameInterval(15)
    private deadChecker() {
        if (Player.localPlayer.character.worldTransform.position.z > -3000) return

        if(this.isDead) return
        this.isDead = true
        
        SoundService.playSound('135885')

        let resurgenceWindow = UIService.show(ResurgenceWindow)
        resurgenceWindow.setInfo(
            // 普通复活
            ()=>{
                this.resetPlayerPositionToCurrentCheckpointStartPosition()
                this.isDead = false
            }, 
            // 返回上一次跳跃的地方复活
            ()=>{
                AdsUtil.playRewardAds(
                    // 广告播放成功, 原地复活
                    ()=>{
                        let playerMD = ModuleService.getModule(PlayerModuleC)
                        Player.localPlayer.character.worldTransform.position = playerMD.getPlayerLastJumpPosition()
                        this.isDead = false
                        // UIService.hide(ResurgenceWindow)
                    },
                    // 广告播放失败, 走普通复活逻辑
                    ()=>{
                        this.resetPlayerPositionToCurrentCheckpointStartPosition()
                        this.isDead = false
                        // UIService.hide(ResurgenceWindow)
                    }
                )
            },
            this
        )
        this.onPlayerDeadEvent.call()
    }

    // 进入下一个检查点
    private onEnterNextCheckpoint(cfg: ISubLevelElement) {
        // 这是最后一关
        if (this.checkpoint.isKindLastCheckpoint()) {
            this.resetCheckpointEffect()
            return
        }
        // 设置下一关检查点
        this.checkpoint.resetCfg(cfg.Next)
        // 服务器记录到下一个检查点
        this.server.net_recode_checkpoint(this.checkpoint.cfg.ID)
        // 如果当前检查点为传送点则传送至下一个检查点
        if(this.checkpoint.isTransferCheckpoint()){
            // 跳转
            this.resetPlayerPositionToCurrentCheckpointStartPosition()
            // 清空冲量
            ModuleService.getModule(PlayerModuleC).clearPlayerDirectionalImpulse()
            // 设置下一关检查点(因为传送点的下一个是起始点)
            this.checkpoint.resetCfg(this.checkpoint.cfg.Next)
            // 服务器记录到下一个检查点(因为传送点的下一个是起始点)
            this.server.net_recode_checkpoint(this.checkpoint.cfg.ID)
            // 抛出进入新关卡事件
            this.onLevelChanged.call(this.checkpoint.cfg.Kind)
        }
        // 普通检查点
        else{
            // 播放进入检查点特效
            EffectService.playAtPosition('73404', this.checkpoint.getCurrentCheckpointStartTriggerBottomPosition())
            // 播放音效
            SoundService.playSound('137564')
        }
        // 显示特效并摆放在下一个检查点的位置
        this.resetCheckpointEffect()
    }

    // 根据当前检查点设置下一个检查点的特效
    private resetCheckpointEffect(){
        if(this.checkpoint.isKindLastCheckpoint()){
            this.checkpointEffect.setVisibility(false)
            return
        }
        this.checkpointEffect.setVisibility(true)
        this.checkpointEffect.worldTransform.position = this.checkpoint.getNextCheckpointStartPosition()
    }

    // 设置玩家位置到当前检查点
    resetPlayerPositionToCurrentCheckpointStartPosition() {
        let resetPosition: Vector
        // 移动到下一个检查点起始位置
        if (this.checkpoint.isTransferCheckpoint()) {
            resetPosition = this.checkpoint.getNextCheckpointStartPosition()
        }
        // 移动到当前检查点起始位置
        else {
            resetPosition = this.checkpoint.getCurrentCheckpointStartPosition()
        }
        // 移动
        Player.localPlayer.character.worldTransform.position = resetPosition
    }

}

export class LevelModuleS extends ModuleS<LevelModuleC, LevelModuleData>{
    onPlayerLevelChangeEvent:Action1<number> = new Action1()

    protected onStart() {

    }

    net_player_play_ads_success() {
        let checkpointCfg = GameConfig.Checkpoint.getElement(this.currentData.checkPointID)
        let levelCfg = GameConfig.Level.getElement(checkpointCfg.Kind)
        let playerMD = ModuleService.getModule(PlayerModuleS)
        playerMD.addPlayerAttr(this.currentPlayerId, Attribute.EnumAttributeType.money, levelCfg.AdsRewardMoneyCount)
    }

    net_recode_checkpoint(checkPointID: number) {
        // 只允许向前记录
        if(this.currentData.checkPointID >= checkPointID) return
        this.currentData.checkPointID = checkPointID
        this.currentData.save(true)
        // 对比新旧检查点
        let oldCheckpointCfg = GameConfig.Checkpoint.getElement(this.currentData.checkPointID)
        let newCheckpointCfg = GameConfig.Checkpoint.getElement(checkPointID)
        if(oldCheckpointCfg.Kind != newCheckpointCfg.Kind){
            this.onPlayerLevelChangeEvent.call(this.currentPlayerId)
        }
    }
}